import socket
import select
import threading
import os
import tkinter as tk
from tkinter import *
from tkinter import scrolledtext
import tkinter.messagebox
import time

##服务器
class App(threading.Thread):

    def __init__(self,master):
        threading.Thread.__init__(self)
        self.ip=StringVar()
        self.port=StringVar()
        self.clients={}
        self.outputs=[]

        self.l_ip=tk.Label(master,text='服务器ip:')
        self.l_ip.grid(row=0,column=0,padx=10,pady=10,sticky=tk.E)
        self.e_ip=tk.Entry(master,textvariable=self.ip)
        self.e_ip.grid(row=0,column=1,padx=10,pady=10,sticky=tk.W)

        self.l_port=tk.Label(master,text='服务器端口:')
        self.l_port.grid(row=1,column=0,padx=10,pady=10,sticky=tk.E)
        self.e_port=tk.Entry(master,textvariable=self.port)
        self.e_port.grid(row=1,column=1,padx=10,pady=10,sticky=tk.W)

        self.btnst=tk.Button(master,text='开启服务',command=self.runServer)
        self.btnst.grid(row=2,column=0,padx=5,pady=5,sticky=tk.E)
        self.btnsp=tk.Button(master,text='断开服务',command=self.stopServer)
        self.btnsp.grid(row=2,column=1,padx=5,pady=5,sticky=tk.W)
        self.btnsp.configure(state='disable')
        

        self.sW=80
        self.sH=30
        self.scr=scrolledtext.ScrolledText(width=self.sW,height=self.sH,wrap=tk.WORD)
        self.scr.grid(row=3,column=0,columnspan=2)
      
   

    def run(self):
        
        while True:
            stdinput, stdoutput, stderr = select.select(self.inputs, self.outputs, self.inputs)
            for obj in stdinput:
            
                if obj is self.s:
                    try:
                        c,addr=self.s.accept()
                    except:
                        print('断开')
                        return
                    self.inputs.append(c) 
                    self.clients[addr]=c
                   
                    for l in self.clients:
                        self.clients[l].sendall('{}已登入'.format(str(addr)).encode('utf-8'))
                    print('{}已登入'.format(str(addr)))
                    if c not in self.clients:
                        self.clients[addr]=c
                    self.scr.insert("insert",'{}已登入\n'.format(str(addr)))
                    self.scr.see(tk.END)
                    self.scr.update()
                else:
                    try:
                        acceptmsg=str(obj.recv(1024),encoding='utf-8')
             
                        print(''.join([acceptmsg,' 客户端口：',str(addr[1])]))
                        
                        accptdata=''.join([acceptmsg,' 客户端口：',str(addr[1])])
                        accptdata=accptdata+'\n'
                        
                        for k in self.clients:
                            self.clients[k].sendall(accptdata.encode('utf-8'))
                        self.scr.insert("insert",accptdata)
                        self.scr.see(tk.END)
                        self.scr.update()
                            
                        
                        if obj not in self.outputs:  
                                self.outputs.append(obj)
                    except ConnectionResetError:
                        adr=obj.getpeername()
                        self.clients={k:v for k,v in self.clients.items() if k!=adr }

                        for b in self.clients:
                            try:
                                self.clients[b].sendall('{}已退出'.format(str(adr)).encode('utf-8'))
                                print('{}已退出'.format(str(addr)))
                                self.scr.insert("insert",'{}已退出\n'.format(str(adr)))
                                self.scr.see(tk.END)
                                self.scr.update()
                            except:
                                print('err')
                                self.scr.insert("insert",'err\n')
                                self.scr.see(tk.END)
                                self.scr.update()
                        if not self.clients:
                            print('最后一位：{}已退出'.format(str(addr)))
                            self.scr.insert("insert",'最后一位：{}已退出\n'.format(str(adr)))
                            self.scr.see(tk.END)
                            self.scr.update()
                        self.inputs.remove(obj)
                        
                    

           
        
    def runServer(self):
        
        self.host=self.ip.get()
        self.port1=self.port.get()
##        self.host='127.0.0.1'
##        self.port1=8800
        t={}
        if not self.host:
            tkinter.messagebox.showinfo('提示','请输入IP地址！')
            return
        
        if not self.port1:
            tkinter.messagebox.showinfo('提示','请输入端口！')
            return
        try:
            self.port1=int(self.port1)
        except:
            print('无效端口！')
            tkinter.messagebox.showinfo('提示','无效端口！')
            return
        
        self.s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        try:
            self.s.bind((self.host,self.port1))
        except:
            print('无效地址！')
            tkinter.messagebox.showinfo('提示','无效地址！')
            return
        self.s.listen(5)
        self.btnst.configure(state='disable')
        self.btnsp.configure(state='normal')
        self.inputs = [self.s]
        
        thread_tcp=app
        print(thread_tcp.is_alive())
        print(threading.enumerate())
        try:
            thread_tcp.start()
            time.sleep(1)
        except:
            if not thread_tcp.is_alive():
                print('not alive')
                         
        print(threading.enumerate())
        print(thread_tcp.name)
        print(thread_tcp.is_alive())
        
        self.scr.insert("insert",'已开启\n')
        self.scr.see(tk.END)
        self.scr.update()
        print('已开启')
                                            


    def stopServer(self):
        self.scr.insert("insert",'已断开\n')
        self.scr.see(tk.END)
        self.scr.update()
        print('已断开')
        self.s.close()
        self.btnst.configure(state='normal')
        self.btnsp.configure(state='disable')
        pass
    

if __name__=='__main__':

        
    root=tk.Tk()


    
    root.title('socketserver')
    root.geometry('600x600')

    app=App(root)

    root.mainloop()

